Oh My Raddit
![1](/img/2018HITCON/Oh My Raddit&v2/1.png)
题目提示,flag 为加密使用的密钥,并且 hint 提示密钥为小写的( assert ENCRYPTION_KEY.islower() )。仔细观察首页上每个a标签的链接,都是形如:http://13.115.255.46/?s=一串16进制数 ,而且这串16进制数的长度刚好可以 被16整除 。16进制解码后就是一个8字节字符串,所以为8字节分组加密。
![2](/img/2018HITCON/Oh My Raddit&v2/2.png)
点击每个链接后,响应状态码均为 303 ,会跳转到相应的网站,而且不同长度的文章标题,对应的s参数值长度也不一样,这说明文章标题可能加密后成为s参数值的一部分。
关于 DES 密码,可以参阅《图解密码技术》中对其的描述:
![3](/img/2018HITCON/Oh My Raddit&v2/3.png)
那么我们可以先找两个有相同子串的标题,将他们对应的链接进行对比(每16个字符一组),找到相同子串对应的密文。如下图,我找到两个标题,都带有 Bypassing W 子串。
![4](/img/2018HITCON/Oh My Raddit&v2/4.png)
由于 3882b1034e878984 后面就不一样了,而相同的子串是 Bypassing W ,所以我们倒过来取8字节,其值就是 3882b1034e878984 对应的明文数据,即:assing+W 对应密文 3882b1034e878984 (这里注意空格需要经过url编码变成+号)。那么接下来我们就可以使用 hashcat 对数据进行破解,结果如下:(其中 617373696e672b57 为 assing+W 的16进制值)
![5](/img/2018HITCON/Oh My Raddit&v2/5.png)
我们使用爆破出来的 ldgonaro 作为解密密钥,对上面的 URL 进行解密,会发现当 URL 长度不是 8 的倍数时,需要在尾部填充数据,使其变成8的倍数。如果刚好是8的倍数,则在尾部 padding 8个 \x08 。
![6](/img/2018HITCON/Oh My Raddit&v2/6.png)
根据这个规则,我们尝试构造链接,下载 app.py 文件。
1 | from Crypto.Cipher import DES |
然后我们访问:http://13.115.255.46/?s=e2272b36277c708bc21066647bc214b8 就可以下载 app.py 文件。可以在代码中看到真正使用的加密密钥为:megnnaro ,所以flag为:hitcon{megnnaro}
1 | # app.py |
Oh My Raddit v2
根据题目提示:Give me SHELL!!! ,应该是考察代码执行。由上一题得到的 app.py 文件,我们得知程序使用了 web.py 框架,直接google搜索相关漏洞。
![7](/img/2018HITCON/Oh My Raddit&v2/7.png)
在文章: Remote Code Execution in Web.py framework 中,我们可以发现 web.py 框架存在代码执行漏洞。那么我们可以先读取一下题目的 requirements.txt 文件,查看 web.py 的版本。 requirements.txt 内容如下:
1 | pycrypto==2.6.1 |
我们可以先安装 0.38 版本的 web.py ,找到 reparam 方法的代码,发现这个版本只是禁用了内建方法,我们只需要绕过即可执行代码,绕过方法和平常做的python沙箱绕过差不多。 reparam 方法代码如下:
![8](/img/2018HITCON/Oh My Raddit&v2/8.png)
根据漏洞作者的描述,_where() 、 query() 、 gen_clause() 这三个方法均调用了 reparam 方法。通过观察 app.py 程序和 db.py 程序,我们会发现 db.py 程序中的 select 调用了 gen_clause() 方法。 app.py 程序中调用过程如下:
1 | get_posts() =====> db.select() =====> db.gen_clause() =====> reparam() |
我们继续观察 app.py 程序,发现有如下两处可以利用,但是进一步分析会发现,只有第二处可以利用。
![10](/img/2018HITCON/Oh My Raddit&v2/10.png)
我们先来分析上图第一处疑似可利用点。该处的 uid 是通过用户传递的 u 参数来确定的,并且最后会用在 where 关键词的后面,我们跟进到 db.py 程序中:
![11](/img/2018HITCON/Oh My Raddit&v2/11.png)
继续跟进 reparam 方法,可以看到用户控制的字段最终会传入 dictionary ,然后作为 eval 函数的 global 属性的值,所以最终不会被执行。( eval(expression, globals=None, locals=None) )
![12](/img/2018HITCON/Oh My Raddit&v2/12.png)
我们再来看第二处可利用点。这处可控的是 limit 字段,最终会传到 chunk 中作为 eval 的第一个参数执行,最终导致代码执行。整个传递过程如下:
![13](/img/2018HITCON/Oh My Raddit&v2/13.png)
根据上面的分析,写出如下 python 程序:
1 | import requests |
获得flag: hitcon{Fr0m_SQL_Injecti0n_t0_Shell_1s_C00L!!!}
参考
https://ctftime.org/writeup/11897